#ifndef __SUBSYSTEM_PICKABLES_H__
#define __SUBSYSTEM_PICKABLES_H__

#include "Subsystem.hpp"
#include "Game/WorldItem.hpp"
#include "Engine/Random.hpp"
#include "GameStack.hpp"
#include <mutex>
#include <unordered_map>
#include "GameLock.hpp"


using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    struct ComponentPlayer;
    class SubsystemBlockBehaviors;
    class SubsystemWaterBlockBehavior;
    class SubsystemGameInfo;
    class SubsystemTimeOfDay;
    class SubsystemTerrain;

    class SubsystemPickables : public Subsystem
    {
    protected:
        // Random m_random;
        // std::map<uint16_t, Pickable *> m_pickableMap;
        
        /**
         * 服务器限制只有有65535个物品，编号范围: 0~65534，少了个65535基本没影响
         * 从开始加载的时候就先将所有的 pickable 对象生成出来
         * 这样虽然开始就占用了大量内存，但是却能减少后期内存碎片化而影响性能的问题
        */

        std::vector<uint16_t> m_pickablesToRemove;

        std::set<uint16_t> m_pickableIdsSet;
        Pickable *m_pickablesTab[UINT16_MAX] = { nullptr };
        GameStack<uint16_t> m_pickableIdStack;

        SpinLock m_pickableMutex;


        SubsystemBlockBehaviors *m_blockBehaviors;
        SubsystemWaterBlockBehavior *m_waterBlockBehavior;
        SubsystemTerrain *m_subsystemTerrain;
        SubsystemGameInfo *m_info;
        SubsystemTimeOfDay *m_timeOfDay;


    public:
        virtual void getNowPickables(std::vector<Pickable*> &vec);
        virtual void getNowNotRemovePickables(std::vector<Pickable*> &vec);

        virtual Pickable* addPickable(int32_t cellValue, uint32_t count, const Vector3 &position, std::shared_ptr<Vector3> velocity, std::shared_ptr<Matrix> stuckMatrix);
        virtual Pickable* createPickable(int32_t cellValue, uint32_t count, const Vector3 &position, std::shared_ptr<Vector3> velocity, std::shared_ptr<Matrix> stuckMatrix);
        virtual Pickable* getPickableById(uint16_t id);
        virtual void onPlayerGetPickable(Pickable *pickable, ComponentPlayer *tmpPlayer, const Vector3 &positionFix, float distance);

        virtual uint32_t clearAllPickable();

    protected:
        void internalSave();

    public:
        SubsystemPickables();
        ~SubsystemPickables();

        virtual void update(float dt) override;
        virtual void load(const nlohmann::json& json) override;
        virtual void save(nlohmann::json& json) override;
        virtual void saveToMsgJson(nlohmann::json &jsonData) override;

        virtual const std::string& getName() const override;
        virtual SubUpdateType getUpdateType() override;
    };
}

#endif